Coverage Report

Created: 2025-05-07 21:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
D:\a\tools.proto\tools.proto\dynamic\src\field\codec\bits.rs
Line
Count
Source
1
// Copyright (c) 2025, BlockProject 3D
2
//
3
// All rights reserved.
4
//
5
// Redistribution and use in source and binary forms, with or without modification,
6
// are permitted provided that the following conditions are met:
7
//
8
//     * Redistributions of source code must retain the above copyright notice,
9
//       this list of conditions and the following disclaimer.
10
//     * Redistributions in binary form must reproduce the above copyright notice,
11
//       this list of conditions and the following disclaimer in the documentation
12
//       and/or other materials provided with the distribution.
13
//     * Neither the name of BlockProject 3D nor the names of its contributors
14
//       may be used to endorse or promote products derived from this software
15
//       without specific prior written permission.
16
//
17
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
21
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29
use crate::field::codec::{ByteCodecBE, ByteCodecLE, Codec};
30
31
pub struct BitCodecLE {
32
    bit_size: usize,
33
    bit_offset: usize,
34
}
35
36
impl BitCodecLE {
37
14
    pub fn new(bit_offset: usize, bit_size: usize) -> Self {
38
14
        Self {
39
14
            bit_size,
40
14
            bit_offset
41
14
        }
42
14
    }
43
}
44
45
impl Codec for BitCodecLE {
46
34
    fn read(&self, buffer: &[u8]) -> u64 {
47
34
        let value = ByteCodecLE.read(buffer);
48
34
        let mask = (1 << self.bit_size) - 1;
49
34
        (value >> self.bit_offset) & mask
50
34
    }
51
52
13
    fn write(&self, buffer: &mut [u8], value: u64) {
53
13
        let mask = (1 << self.bit_size) - 1;
54
13
        let reset_mask = !(mask << self.bit_offset);
55
13
        let original = ByteCodecLE.read(buffer);
56
13
        let clean = original & reset_mask;
57
13
        let value = (value & mask) << self.bit_offset;
58
13
        let new = clean | value;
59
13
        ByteCodecLE.write(buffer, new);
60
13
    }
61
}
62
63
pub struct BitCodecBE {
64
    bit_size: usize,
65
    bit_offset: usize,
66
}
67
68
impl BitCodecBE {
69
7
    pub fn new(bit_offset: usize, bit_size: usize) -> Self {
70
7
        Self {
71
7
            bit_size,
72
7
            bit_offset
73
7
        }
74
7
    }
75
}
76
77
impl Codec for BitCodecBE {
78
4
    fn read(&self, buffer: &[u8]) -> u64 {
79
4
        let mask = (1 << self.bit_size) - 1;
80
4
        let value = ByteCodecBE.read(buffer);
81
4
        (value >> (8 - (self.bit_size % 8) - self.bit_offset)) & mask
82
4
    }
83
84
3
    fn write(&self, buffer: &mut [u8], value: u64) {
85
3
        let mask = (1 << self.bit_size) - 1;
86
3
        let reset_mask = !(mask << (8 - (self.bit_size % 8) - self.bit_offset));
87
3
        let original = ByteCodecBE.read(buffer);
88
3
        let clean = original & reset_mask;
89
3
        let value = (value & mask) << (8 - (self.bit_size % 8) - self.bit_offset);
90
3
        let new = clean | value;
91
3
        ByteCodecBE.write(buffer, new);
92
3
    }
93
}
94
95
#[cfg(test)]
96
mod tests {
97
    use crate::field::codec::bits::{BitCodecBE, BitCodecLE};
98
    use crate::field::codec::Codec;
99
100
    #[test]
101
1
    fn little_endian() {
102
1
        let buffer = [0xFF, 0xFF, 0xFF, 0xFF];
103
1
        assert_eq!(BitCodecLE::new(0, 32).read(&buffer[0..4]), 0xFFFFFFFF);
104
1
        assert_eq!(BitCodecLE::new(0, 1).read(&buffer[0..1]), 1);
105
1
        assert_eq!(BitCodecLE::new(0, 4).read(&buffer[0..1]), 0xF);
106
1
        assert_eq!(BitCodecLE::new(4, 4).read(&buffer[0..1]), 0xF);
107
1
    }
108
109
    #[test]
110
1
    fn big_endian() {
111
1
        let buffer = [0xAB, 0xF0];
112
1
        assert_eq!(BitCodecBE::new(0, 12).read(&buffer[0..2]), 0xABF);
113
1
        let mut buffer = [0x0, 0x0];
114
1
        BitCodecBE::new(0, 4).write(&mut buffer[0..1], 0xF);
115
1
        assert_eq!(BitCodecBE::new(0, 4).read(&buffer[0..1]), 0xF);
116
1
        BitCodecBE::new(0, 12).write(&mut buffer[0..2], 0xABF);
117
1
        assert_eq!(BitCodecBE::new(0, 12).read(&buffer[0..2]), 0xABF);
118
1
        BitCodecBE::new(1, 7).write(&mut buffer[1..2], 127);
119
1
        assert_eq!(BitCodecBE::new(1, 7).read(&buffer[1..2]), 127);
120
1
    }
121
}